package com.gongyinlian.personalprofilewebsiteserver.utils;

import cn.hutool.crypto.digest.BCrypt;
import lombok.extern.slf4j.Slf4j;

/**
 * 密码工具类
 * 使用 BCrypt 算法进行密码加密和验证
 * 
 * @author personal-profile-website
 * @date 2024-10-27
 */
@Slf4j
public class PasswordUtil {
    
    /**
     * BCrypt 加密强度（4-31，推荐10-12）
     */
    private static final int BCRYPT_ROUNDS = 10;
    
    /**
     * 加密密码
     * 
     * @param rawPassword 明文密码
     * @return 加密后的密码
     */
    public static String encode(String rawPassword) {
        if (rawPassword == null || rawPassword.trim().isEmpty()) {
            throw new IllegalArgumentException("密码不能为空");
        }
        return BCrypt.hashpw(rawPassword, BCrypt.gensalt(BCRYPT_ROUNDS));
    }
    
    /**
     * 验证密码
     * 
     * @param rawPassword 明文密码
     * @param encodedPassword 加密后的密码
     * @return true-匹配，false-不匹配
     */
    public static boolean matches(String rawPassword, String encodedPassword) {
        if (rawPassword == null || encodedPassword == null) {
            return false;
        }
        try {
            return BCrypt.checkpw(rawPassword, encodedPassword);
        } catch (Exception e) {
            log.error("密码验证失败: {}", e.getMessage());
            return false;
        }
    }
    
    /**
     * 判断密码强度
     * 
     * @param password 密码
     * @return 0-弱，1-中，2-强
     */
    public static int getPasswordStrength(String password) {
        if (password == null || password.length() < 6) {
            return 0; // 弱
        }
        
        int score = 0;
        
        // 长度大于8
        if (password.length() >= 8) {
            score++;
        }
        
        // 包含数字
        if (password.matches(".*\\d+.*")) {
            score++;
        }
        
        // 包含小写字母
        if (password.matches(".*[a-z]+.*")) {
            score++;
        }
        
        // 包含大写字母
        if (password.matches(".*[A-Z]+.*")) {
            score++;
        }
        
        // 包含特殊字符
        if (password.matches(".*[!@#$%^&*()_+\\-=\\[\\]{};':\"\\\\|,.<>/?]+.*")) {
            score++;
        }
        
        // 评分：0-2分为弱，3分为中，4-5分为强
        if (score <= 2) {
            return 0; // 弱
        } else if (score == 3) {
            return 1; // 中
        } else {
            return 2; // 强
        }
    }
    
    /**
     * 验证密码格式
     * 
     * @param password 密码
     * @return true-格式正确，false-格式错误
     */
    public static boolean isValidPassword(String password) {
        if (password == null || password.trim().isEmpty()) {
            return false;
        }
        
        // 长度至少6位
        if (password.length() < 6) {
            return false;
        }
        
        // 最多32位
        if (password.length() > 32) {
            return false;
        }
        
        // 不能包含空格
        if (password.contains(" ")) {
            return false;
        }
        
        return true;
    }
    
    /**
     * 生成随机密码
     * 
     * @param length 密码长度（最少6位）
     * @return 随机密码
     */
    public static String generateRandomPassword(int length) {
        if (length < 6) {
            length = 6;
        }
        
        String upperCase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        String lowerCase = "abcdefghijklmnopqrstuvwxyz";
        String numbers = "0123456789";
        String special = "!@#$%^&*";
        
        String allChars = upperCase + lowerCase + numbers + special;
        
        StringBuilder password = new StringBuilder();
        
        // 确保至少包含一个大写、小写、数字和特殊字符
        password.append(upperCase.charAt((int) (Math.random() * upperCase.length())));
        password.append(lowerCase.charAt((int) (Math.random() * lowerCase.length())));
        password.append(numbers.charAt((int) (Math.random() * numbers.length())));
        password.append(special.charAt((int) (Math.random() * special.length())));
        
        // 填充剩余字符
        for (int i = 4; i < length; i++) {
            password.append(allChars.charAt((int) (Math.random() * allChars.length())));
        }
        
        // 打乱顺序
        char[] chars = password.toString().toCharArray();
        for (int i = chars.length - 1; i > 0; i--) {
            int j = (int) (Math.random() * (i + 1));
            char temp = chars[i];
            chars[i] = chars[j];
            chars[j] = temp;
        }
        
        return new String(chars);
    }
}

